package cn.edu.jiangnan.cashmanagement.common.dao;

import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import javax.inject.Inject;
import javax.inject.Named;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Repository;

import cn.edu.jiangnan.cashmanagement.common.util.PaginationSupport;

/**
 * 公共的数据访问层对象封装 使用泛型
 * */
@Repository
public class CommonDao<T> implements IDao<T> {

	private Class<T> clazz;

	public Class<T> getClazz() {
		return clazz;
	}

	public void setClazz(Class<T> clazz) {
		this.clazz = clazz;
	}

	public CommonDao() {
	}
	
	@Inject
	@Named(value = "hibernateTemplate")
	HibernateTemplate hbmTemplate;

	@Override
	public Long save(T t) {
		return (Long) hbmTemplate.save(t);
	}

	@SuppressWarnings(value = "unchecked")
	public List<T> getListForPage(final String hql, final int start,
			final int size) {

		List<T> list = hbmTemplate.executeFind(new HibernateCallback() {

			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Query query = session.createQuery(hql);
				query.setFirstResult(start);
				if (size > 0) {
					query.setMaxResults(size);
				}
				List<T> list = query.list();
				return list;
			}

		});
		return list;
	}

	@SuppressWarnings(value = "unchecked")
	protected List<T> getListForPage(final Class<T> arg,
			final Criterion[] criterions, final int start, final int size) {

		List<T> list = hbmTemplate.executeFind(new HibernateCallback() {

			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Criteria criteria = session.createCriteria(arg);
				// 循环遍历添加约束条件
				for (int i = 0; i < criterions.length; i++) {
					criteria.add(criterions[i]);
				}
				criteria.setFirstResult(start);
				criteria.setMaxResults(size);
				return criteria.list();
			}

		});
		return list;
	}

	@Override
	public Boolean delete(Long id) {
		Long[] idArr = new Long[] { id };
		return deleteAll(Arrays.asList(idArr));
	}

	@Override
	public Boolean deleteAll(List<Long> ids) {
		List<T> entities = new ArrayList<T>(ids.size());
		for (Long id : ids) {
			entities.add(hbmTemplate.get(clazz, id));
		}
		hbmTemplate.deleteAll(entities);
		return true;
	}

	@Override
	public List<T> find(T t, int start, int limit) {
		return null;
	}

	@Override
	public Boolean update(T t) {
		hbmTemplate.update(t);
		return true;
	}

	public PaginationSupport<T> findPageByCriteria(
			final DetachedCriteria detachedCriteria) {
		return findPageByCriteria(detachedCriteria, PaginationSupport.PAGESIZE,
				0);
	}

	public PaginationSupport<T> findPageByCriteria(
			final DetachedCriteria detachedCriteria, final int startIndex) {
		return findPageByCriteria(detachedCriteria, PaginationSupport.PAGESIZE,
				startIndex);
	}

	@SuppressWarnings(value = "unchecked")
	public PaginationSupport<T> findPageByCriteria(
			final DetachedCriteria detachedCriteria, final int pageSize,
			final int startIndex) {
		return (PaginationSupport<T>) hbmTemplate
				.executeFind(new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException {
						Criteria criteria = detachedCriteria
								.getExecutableCriteria(session);
						int totalCount = ((Integer) criteria.setProjection(
								Projections.rowCount()).uniqueResult())
								.intValue();
						criteria.setProjection(null);
						List<T> items = criteria.setFirstResult(startIndex)
								.setMaxResults(pageSize).list();
						PaginationSupport<T> ps = new PaginationSupport<T>(
								items, totalCount, pageSize, startIndex);
						return ps;
					}

				});
	}

	@SuppressWarnings(value = "unchecked")
	public List<T> findAllByCriteria(final DetachedCriteria detachedCriteria) {
		return (List<T>) hbmTemplate.executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException {
				Criteria criteria = detachedCriteria
						.getExecutableCriteria(session);
				return criteria.list();
			}
		});
	}

	@Override
	public T get(Long id) {
		return (T) hbmTemplate.get(clazz, id);
	}

	// public int getCountByCriteria(final DetachedCriteria detachedCriteria) {
	// Integer count = (Integer) hbmTemplate.executeFind(
	// new HibernateCallback() {
	// public Object doInHibernate(Session session)
	// throws HibernateException {
	// Criteria criteria = detachedCriteria
	// .getExecutableCriteria(session);
	// return criteria.setProjection(Projections.rowCount())
	// .uniqueResult();
	// }
	// });
	// return count.intValue();
	// }

}
